﻿/*
** Xin YUAN, 2023, BSD (2)
*/

////////////////////////////////////////////////////////////////////////////////

//sync

#if defined(WIN32)

#include "windows/sys_sync.h"

#elif defined(__linux__)

#include "linux/sys_sync.h"

#else

#error This OS system is not supported!

#endif

//sync_lock

class sync_lock
{
public:
	sync_lock(sync_mutex& m, bool bInitialLock = true) noexcept : m_mutex(m), m_bLocked(false)
	{
		if ( bInitialLock )
			Lock();
	}
	sync_lock(const sync_lock&) = delete;
	~sync_lock() noexcept
	{
		if ( m_bLocked )
			Unlock();
	}

	sync_lock& operator=(const sync_lock&) = delete;

	void Lock() noexcept
	{
		assert( !m_bLocked );
		m_mutex.Lock();
		m_bLocked = true;
	}
	void Unlock() noexcept
	{
		assert( m_bLocked );
		m_mutex.Unlock();
		m_bLocked = false;
	}

private:
	sync_mutex& m_mutex;
	bool m_bLocked;
};

//sync_fence

class sync_fence
{
public:
	sync_fence() noexcept : m_value(0), m_dest(0)
	{
	}
	sync_fence(const sync_fence&) = delete;
	~sync_fence() noexcept
	{
	}

	sync_fence& operator=(const sync_fence&) = delete;

	bool Init() noexcept
	{
		if ( !m_mutex.Init() )
			return false;
		m_cond.Init();
		return true;
	}

	void Reset(uint64_t uInitialValue, uint64_t uDestValue) noexcept
	{
		m_value = uInitialValue;
		m_dest = uDestValue;
	}
	void Wait() noexcept
	{
		m_mutex.Lock();
		while ( m_value < m_dest )
			m_cond.Wait(m_mutex);
		m_mutex.Unlock();
	}
	void SetValue(uint64_t v) noexcept
	{
		m_mutex.Lock();
		m_value = v;
		m_cond.Signal();
		m_mutex.Unlock();
	}
	void AddValue(uint64_t v) noexcept
	{
		m_mutex.Lock();
		m_value += v;
		m_cond.Signal();
		m_mutex.Unlock();
	}

private:
	sync_mutex m_mutex;
	sync_condition m_cond;

	uint64_t m_value;
	uint64_t m_dest;
};

////////////////////////////////////////////////////////////////////////////////
